home *** CD-ROM | disk | FTP | other *** search
- static char rcsid[] = "@(#) $Header: chat.c,v 2.1 90/03/04 20:18:18 dl9sau Exp $";
-
- #include <sys/types.h>
-
- #include <ctype.h>
- #include <signal.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <termio.h>
- #include <sys/time.h>
-
- #define SERVER "*:3600"
- #define RCFILE ".convrc"
- #define EINCONF "convers: error in config -- %s"
- #define USAGE "usage: convers [-c channel][-s host:service][-n name][-i invite][-l l][-w l]\n"
-
- extern char *getenv();
- extern char *optarg;
- extern int optind;
- extern struct sockaddr *build_sockaddr();
- extern void exit();
- extern void perror();
-
- static struct termio prev_termio;
-
- /*---------------------------------------------------------------------------*/
-
- static void sigpipe_handler(sig, code, scp)
- int sig, code;
- /* struct sigcontext *scp; */
- {
- /* scp->sc_syscall_action = SIG_RETURN; */
- }
-
- /*---------------------------------------------------------------------------*/
-
- static void stop(arg)
- char *arg;
- {
- if (arg) perror(arg);
- ioctl(0, TCSETA, &prev_termio);
- exit(0);
- }
-
- /*---------------------------------------------------------------------------*/
-
- static int scan_config(server, name, channel, commands)
- char *server, *name;
- int *channel;
- char *commands;
- {
- FILE * fp = (FILE *) 0;
- char buf1[1024], buf2[128];
- char *p, *q;
- int i;
-
- sprintf(buf2, "%s/%s", getenv("HOME"), RCFILE);
- *commands = '\0';
- if (!(fp = fopen(buf2, "r")))
- return 1;
- while (fgets(buf1, sizeof(buf1), fp)) {
- if (*buf1 == '\n' || *buf1 == '#') continue;
- for ((p = buf1, i = 0); *p; p++)
- if (*p == ':') i++;
- if (i >= 2) {
- for ((q = buf2, p = buf1); *p != ':'; *q++ = *p++) ;
- *q='\0';
- p++;
-
- q = strrchr(p, ':');
- *q = '\0';
- if (!strcmp(buf2, "server")) strcpy(server, p);
- else if (!strcmp(buf2, "name")) strcpy(name, p);
- else if (!strcmp(buf2, "channel")) *channel = atoi(p);
- else {
- fprintf(stderr, EINCONF, buf1);
- stop(0);
- }
- }
- else {
- if (strchr(buf1, "/c")) {
- fprintf(stderr, EINCONF, buf1);
- stop(0);
- }
- strcat(commands, buf1);
- }
- }
- fclose(fp);
- return 0;
- }
-
- /*---------------------------------------------------------------------------*/
-
- main(argc, argv)
- int argc;
- char **argv;
- {
-
- char *server = SERVER;
- char name[16];
- char commands[1028];
- char buffer[2048];
- char c;
- char *p, *q;
- char inbuf[2048];
- char outbuf[2048];
- int addrlen;
- int ch;
- int channel = 0;
- int errflag = 0;
- int echo;
- int i;
- int incnt = 0;
- int mask;
- int outcnt = 0;
- int size;
- /* struct sigvec vec; */
- struct sockaddr *addr;
- struct termio curr_termio;
-
- /* vec.sv_mask = vec.sv_flags = 0; */
- /* vec.sv_handler = sigpipe_handler; */
- /* sigvector(SIGPIPE, &vec, (struct sigvec *) 0); */
-
- if (ioctl(0, TCGETA, &prev_termio)) stop(*argv);
- if (ioctl(0, TCGETA, &curr_termio)) stop(*argv);
- echo = curr_termio.c_lflag & ECHO;
- curr_termio.c_lflag = 0;
- curr_termio.c_cc[VMIN] = 1;
- curr_termio.c_cc[VTIME] = 0;
- if (ioctl(0, TCSETA, &curr_termio)) stop(*argv);
-
- strcpy(name, getenv("LOGNAME"));
- /* scan_config(socket, name, &channel, commands); */
- scan_config(server, name, &channel, commands);
-
- while ((ch = getopt(argc, argv, "c:i:l:n:s:w:")) != EOF)
- switch (ch) {
- case 'c':
- channel = atoi(optarg);
- break;
- case 's':
- server = optarg;
- break;
- case 'n':
- strcpy(name, optarg);
- break;
- case 'l':
- if (p = q = strchr(commands, "/l")) { /* Alten Befehl entfernen */
- for (q; (*q && *q != '\n'); q++) ;
- if (*q++) {
- while (*p++ = *q++) ;
- }
- }
- break;
- strcat(commands, "/l ");
- if (*optarg == 'q' || *optarg == 'l')
- strcat(commands, optarg);
- strcat(commands, "\n");
- break;
- case 'w':
- if (p = q = strchr(commands, "/w")) { /* Alten Befehl entfernen */
- for (q; (*q && *q != '\n'); q++) ;
- if (*q++) {
- while (*p++ = *q++) ;
- }
- }
- strcat(commands, "/w ");
- if (*optarg == 'q' || *optarg == 'l')
- strcat(commands, optarg);
- strcat(commands, "\n");
- break;
- case 'i':
- sprintf(commands, "/i %s\n", optarg);
- break;
- case '?':
- errflag = 1;
- break;
- }
-
- if (errflag || optind < argc || !(addr = build_sockaddr(server, &addrlen))) {
- fprintf(stderr, USAGE);
- stop(0);
- }
- close(3);
- if (socket(addr->sa_family, SOCK_STREAM, 0) != 3) stop(*argv);
- if (connect(3, addr, addrlen)) stop(*argv);
-
- sprintf(inbuf, "/NAME %s %d\n", name, channel);
- strcat(inbuf, commands);
-
- if (write(3, inbuf, (unsigned) strlen(inbuf)) < 0) stop(*argv);
- for (; ; ) {
- mask = 011;
- select(4, &mask, 0, 0, (struct timeval *) 0);
- if (mask & 1) {
- do {
- if ((size = read(0, buffer, sizeof(buffer))) <= 0) stop(0);
- for (i = 0; i < size; i++) {
- c = buffer[i];
- if (c == '\r') c = '\n';
- if (c == prev_termio.c_cc[VERASE]) {
- if (incnt) {
- incnt--;
- if (echo && write(1, "\b \b", 3) < 0) stop(*argv);
- }
- } else if (c == prev_termio.c_cc[VKILL]) {
- for (; incnt; incnt--)
- if (echo && write(1, "\b \b", 3) < 0) stop(*argv);
- } else if (echo && c == 18) {
- if (write(1, "^R\n", 3) < 0) stop(*argv);
- if (write(1, inbuf, (unsigned) incnt) < 0) stop(*argv);
- } else {
- inbuf[incnt++] = c;
- if (echo && write(1, &c, 1) < 0) stop(*argv);
- }
- if (c == '\n' || incnt == sizeof(inbuf) - 1) {
- if (*inbuf == '!') {
- inbuf[incnt] = '\0';
- if (ioctl(0, TCSETA, &prev_termio)) stop(*argv);
- system(inbuf + 1);
- if (ioctl(0, TCSETA, &curr_termio)) stop(*argv);
- if (write(1, "!\n", 2) < 0) stop(*argv);
- } else {
- if (write(3, inbuf, (unsigned) incnt) < 0) stop(*argv);
- }
- incnt = 0;
- }
- }
- } while (incnt);
- } else {
- size = read(3, buffer, sizeof(buffer));
- if (size <= 0) stop(0);
- for (i = 0; i < size; i++) {
- c = buffer[i];
- if (c != '\r') outbuf[outcnt++] = c;
- if (c == '\n' || outcnt == sizeof(outbuf)) {
- if (write(1, outbuf, (unsigned) outcnt) < 0) stop(*argv);
- outcnt = 0;
- }
- }
- }
- }
- }
-